import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;


public class ROCcurveDrawer {

	private TreeMap<Integer, Integer> distributionMe;
	private TreeMap<Integer, Integer> distributionOther;
	private int[][] distributionMatrix;
	private double[][] rocMatrix;
	private int max;
	
	public ROCcurveDrawer(String disFileMe, String disFileOther){
		this.distributionMe = new TreeMap<Integer, Integer>();
		this.distributionOther = new TreeMap<Integer, Integer>();
		
		try {
			//create distributionMe
			BufferedReader brMe = new BufferedReader(new FileReader(disFileMe));
			String oneLineMe;
			while((oneLineMe = brMe.readLine())!=null){
				StringTokenizer stMe = new StringTokenizer(oneLineMe,",");
				String xStr = stMe.nextToken();
				String yStr = stMe.nextToken();
				int x = Integer.parseInt(xStr);
				int y = Integer.parseInt(yStr);
				this.distributionMe.put(x, y);
			}
			brMe.close();
			
			//create distributionOther
			BufferedReader brOther = new BufferedReader(new FileReader(disFileOther));
			String oneLineOther;
			while((oneLineOther = brOther.readLine())!=null){
				StringTokenizer stOther = new StringTokenizer(oneLineOther,",");
				String xStr = stOther.nextToken();
				String yStr = stOther.nextToken();
				int x = Integer.parseInt(xStr);
				int y = Integer.parseInt(yStr);
				this.distributionOther.put(x, y);
			}
			brOther.close();
			
			//init distributionMatrix
			this.max = getMaxXValue();
			distributionMatrix = new int[max+1][3];
			for(int i=0;i<max+1;i++){
				for(int j=0;j<3;j++){
					distributionMatrix[i][j] = 0;
				}
			}
			for(int k=0;k<max+1;k++){
				distributionMatrix[k][0] = k;
			}
			
			//get dismatrix
			getDistributionMatrix();
			
			//init rocMatrix
			rocMatrix = new double[max+1][2];
			for(int i=0;i<max+1;i++){
				for(int j=0;j<2;j++){
					rocMatrix[i][j] = 0;
				}
			}
			
			//get roc matrix
			getRocMatrix();
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	private int getMaxXValue(){
		int maxMe = distributionMe.lastKey();
		int maxOther = distributionOther.lastKey();
		return Math.max(maxMe, maxOther);
	}
	
	private void getDistributionMatrix(){
		// set Me value in matrix
		Iterator ite1 = this.distributionMe.entrySet().iterator();
		while(ite1.hasNext()){
			Map.Entry entry = (Map.Entry)ite1.next();
			int x = (Integer)entry.getKey();
			int yMe = (Integer)entry.getValue();
			distributionMatrix[x][1] = yMe;
		}
		// set Other value in matrix
		Iterator ite2 = this.distributionOther.entrySet().iterator();
		while(ite2.hasNext()){
			Map.Entry entry = (Map.Entry)ite2.next();
			int x = (Integer)entry.getKey();
			int yOther = (Integer)entry.getValue();
			distributionMatrix[x][2] = yOther;
		}
	}
	
	
	
	
	public void getRocMatrix(){
		//count total num
		int totalNumberOfMe = 0;
		for(int i=0;i<max+1;i++){
			totalNumberOfMe = totalNumberOfMe + distributionMatrix[i][1];
		}
		int totalNumberOfOther = 0;
		for(int i=0;i<max+1;i++){
			totalNumberOfOther = totalNumberOfOther + distributionMatrix[i][2];
		}
		
		double FP = 0;
		double TP = 0;
		for(int i=0;i<max+1;i++){
			int countMe = countNumGreaterThanBorder(i, distributionMatrix, 1);
			FP = (double)(countMe)/totalNumberOfMe;
			int countOther = countNumGreaterThanBorder(i, distributionMatrix, 2);
			TP = (double)(countOther)/totalNumberOfOther;
			this.rocMatrix[i][0] = FP;
			this.rocMatrix[i][1] = TP;
		}
		
	}
	
	private int countNumGreaterThanBorder(int border, int[][] matrix, int column){
		int count = 0;
		for(int i=border;i<max+1;i++){
			count = count + matrix[i][column];
		}
		return count;
	}
	
	
	
	public void writeDistributionMatrix(String outputFileName){
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(outputFileName));
			bw.write("Distance,Me(distribution),Other(distribution)");
			bw.newLine();
			for(int i=0;i<max+1;i++){
				for(int j=0;j<3;j++){
					bw.write(distributionMatrix[i][j]+",");
				}
				bw.newLine();
			}
			bw.flush();
			bw.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	
	public void writeROCMatrix(String outputFileName){
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(outputFileName));
			bw.write("FP,TP");
			bw.newLine();
			for(int i=0;i<max+1;i++){
				for(int j=0;j<2;j++){
					bw.write(rocMatrix[i][j]+",");
				}
				bw.newLine();
			}
			bw.flush();
			bw.close();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	
	
	
	
	
	public static void main(String args[]){
		ROCcurveDrawer roc1 = new ROCcurveDrawer("out/freq_distance_me.csv","out/freq_distance_other.csv");
		roc1.writeDistributionMatrix("out/dis_matrix_freq.csv");
		roc1.writeROCMatrix("out/roc_matrix_freq.csv");
		
		ROCcurveDrawer roc2 = new ROCcurveDrawer("out/ngram_distance_me.csv","out/ngram_distance_other.csv");
		roc2.writeDistributionMatrix("out/dis_matrix_ngram.csv");
		roc2.writeROCMatrix("out/roc_matrix_ngram.csv");
		
		TwoModelCombiner combiner1 = new TwoModelCombiner("out/freq_distance_me.csv","out/ngram_distance_me.csv");
		combiner1.displayMapForDistance("out/combination_distance_me.csv");
		TwoModelCombiner combiner2 = new TwoModelCombiner("out/freq_distance_other.csv","out/ngram_distance_other.csv");
		combiner2.displayMapForDistance("out/combination_distance_other.csv");
		
		ROCcurveDrawer roc_combi = new ROCcurveDrawer("out/combination_distance_me.csv","out/combination_distance_other.csv");
		roc_combi.writeDistributionMatrix("out/dis_matrix_combi.csv");
		roc_combi.writeROCMatrix("out/roc_matrix_combi.csv");
		
	}
}
